open Uav_data
open Target

(* represent capacity ressources of the problem *)
type ressources_t = {
  ball: int array;
  video: int array;
}

type planning_t = {
  tasks: int array;
  res: ressources_t;
  plans: int array array;
}

(* returns cost of a plan *)
let plan_cost = fun plans k ->
  let c = ref 0 in
  for i=1 to Array.length plans.(k) -1 do
    c:= !c + time.(k).(plans.(k).(i-1)).(plans.(k).(i))
  done;
    !c

(* cost of a planning solution *)
let cost = fun planning ->
  let c = Array.mapi (fun k _ -> plan_cost planning.plans k) planning.plans in
    Utils.max_array c

(* returns cost of task t in plan of ac_id *)
let cost_of_task = fun t plan ac_id ->
  let i = Utils.position_in_array t plan in
    time.(ac_id).(i-1).(i) + time.(ac_id).(i).(i+1) - time.(ac_id).(i-1).(i+1)

(* return available machine for task t considering ressources res *)
let available_machine_for_task = fun t res ->
  let l = Array.to_list (Array.init m (fun i -> i)) in
    if ttype.(t) = Dr
    then List.filter (fun i -> res.ball.(i)>0) l
    else l

(* select randomly an element of a list *)
let select_from_list = fun l -> List.nth l (Random.int (List.length l))

(* generate an allocation respecting ressources res *)
let generate_random_alloc = fun res ->
    Array.init n 
      (fun i ->
	 let machine = select_from_list (available_machine_for_task i res) in
	   if ttype.(i) = Dr then res.ball.(machine) <- res.ball.(machine) -1;
	   (* returns the chosen machine *)
	   machine)
      
(* generate plans with a random allocation *)
let generate_first_plans = fun res ->
  let tasks = generate_random_alloc res in
    Insertion.generate_plans tasks

(* returns the cost of each task from the allocation tasks and the 
   generated plans *)
let cost_of_all_tasks = fun tasks plans ->
  Array.mapi 
    (fun t ac_id -> cost_of_task t plans.(ac_id) ac_id)
    tasks

(* print solutions costs *)
let print_solution = fun tasks plans ->
    (*Array.iter (Printf.printf "%d\t") tasks;
    print_newline();
    Array.iter (Printf.printf "%d\t") (cost_of_all_tasks tasks plans);
    print_newline();*)
    Array.iter 
      (fun c -> Printf.printf "%6d\t " c) 
      (Array.mapi (fun i _ -> plan_cost plans i) plans);
    print_newline()

(* remove task t from planning solution planning *)
let remove_task_from_plan = fun t planning ->
  let tasks = planning.tasks
  and plans = planning.plans
  and res = planning.res in 
    if ttype.(t) = Dr then res.ball.(tasks.(t)) <- res.ball.(tasks.(t)) +1;
    plans.(tasks.(t)) <- Array.of_list 
      (List.filter (fun x -> x<>t) (Array.to_list plans.(tasks.(t))));
    tasks.(t) <- -1

let planning_copy = fun planning ->
  { tasks = Array.copy planning.tasks;
    res = { ball = Array.copy planning.res.ball; video = Array.copy planning.res.video };
    plans = Array.map Array.copy planning.plans;
  }
